<?php

class lb_session{

	protected $session_id = false;
	protected $clean_time = 1200; //20 mins
	protected $errs	= array();

	/**
	 * constructor of lb_session
	 * 
	 * @access	public
	 * @author	Armin Borumand
	 */
	function __construct(){
	
		global $lb;
		
		$this->clean($this->clean_time);
		//@session_start();
		$this->session_id = $this->load();

		//@future: if the session not exist!!
		if($this->session_id == false){
			//create new session
			if(($this->session_id = $this->create()) == false){
				if(!isset($lb['error'])){
					$lb['error'] = array();
				}
				$lb['error'] = array_merge($lb['error'], $this->get_errors());
				$lb['task']	 = 'error';
			}
		}
	}

	/**
	 * create a new session
	 * 
	 * @access	protected
	 * @author	Armin Borumand
	 * @return	int	added session id
	 */
	function create(){
		global $lb;

		if($this->session_id != false){
			$this->destroy();
		}
		
		$session_id = lb_system::hash(uniqid(rand(), true));
		$check_params = $this->check_params();	
		
	/*
		Insert into session database a new row (means create new session)
		and return row id
	*/		
		$params = array(
				array($session_id, 'text'),
				array($check_params, 'hash')
				);
		$query  = 'INSERT INTO #__session
				(session_id, time, check_params) 
				VALUES 
				(#, NOW(), #)';
		
		$result = $lb['db']->query($query, $params);
		
		if($result['num_of_rows'] == 1){
			lb_system::setcookie('sid' , $session_id, 'session');
			return intval($result['insert_id']);
		}else{
			$this->errs[] = sprintf(LANG_SESSION_ERROR_SESSION_CREATION, __CLASS__, __FUNCTION__);
			return false;
		}
		
	}
	
	/**
	 * load current session id
	 * 
	 * @access	protected
	 * @author	Armin Borumand
	 * @return	int	session id
	 */
	function load(){
		global $lb;
		
		//get session id
		if($this->session_id == false){
			//fetch from a global var as $_COOKIE current session id
			//check in session database id and some condition
			$sid = lb_system::getcookie('sid');
			$check_params = $this->check_params();	
			
			if($sid != false){
				$params = array(
						array($sid, 'text'),
						array($check_params, 'hash')
						);
				$query = 'SELECT id FROM #__session 
						WHERE session_id = # AND check_params = #';
				$result = $lb['db']->query($query, $params);
				
				if($result['num_of_rows'] == 1){
					$id = intval($result['rows'][0]['id']);
					$params = array(
							array($sid, 'text')
							);
					$query = 'UPDATE #__session 
							SET time = NOW() 
							WHERE session_id = #';
					$lb['db']->query($query, $params);
				}else{
					$id = false;
				}
			}else{
				$id = false;
			}
			
		}else{
			$id = $this->session_id;
		}
		
		return $id;
	
	}
	
	/**
	 * Regenerate session id and pass
	 *
	 * @access	public
	 * @author	Armin Borumand
	 * @return	boolean	true on success and false on failure
	 */
	function regenerate(){
		global $lb;
		
		if($this->session_id == false){
			$this->errs[] = sprintf(LANG_SESSION_ERROR_NO_SESSION, __CLASS__, __FUNCTION__);
			return false;
		}
		
		$new_sid	  = lb_system::hash(uniqid(rand(), true));
		//set session id
		$params = array(
				array($new_sid, 'text'),
				array($this->session_id, 'int')
				);
		$query = 'UPDATE #__session 
				SET session_id = #
				WHERE id = #';
		$result = $lb['db']->query($query, $params);
			
		if($result['num_of_rows'] == 1){
			lb_system::setcookie('sid' ,$new_sid, 'session');
			return true;
		}else{
			$this->errs[] = sprintf(LANG_SESSION_ERROR_UPDATE_DB, __CLASS__, __FUNCTION__);
			return false;
		}
			
		
	}
	
	/**
	 * set session variable
	 * 
	 * @access	public
	 * @author 	Omid Mottaghi
	 * @author 	Armin Borumand
	 * @param 	string	variable name
	 * @param	string	variable value
	 */
	function set($var, $val){
		global $lb;
		
		$params = array(
				array($this->session_id, 'int'),
				array($var, 'text'),
				array($val, 'text')
				);
		$query = 'INSERT INTO #__session_store
				(id, var, val) 
				VALUES 
				(#, #, #)';
		$result = $lb['db']->query($query, $params);
		if($result['num_of_rows'] == 1){
			return true;
		}else{
			$this->errs[] = sprintf(LANG_SESSION_ERROR_SET, __CLASS__, __FUNCTION__);
			return false;
		}
	}
	
	/**
	 * return value of a key in session
	 * 
	 * @access	public
	 * @author	Omid Mottaghi
	 * @author	Armin Borumand
	 * @param	string/array	variable name
	 * @return	string/array	variable value
	 */
	function get($vars){

		global $lb;
		
		$query = 'SELECT var, val FROM #__session_store
				WHERE id = # AND (';
		$params = array(
				array($this->session_id, 'int')
				);
		
		if(!is_array($vars)){
			$vars = array($vars);
			$str  = true;
		}
		
		foreach($vars as $var){
			$query .= ' var = # OR ';
			array_push($params, array($var, 'text'));
		}
		
		$query  = substr($query, 0, strlen($query)-3);
		$query .= ')';
		
		$result = $lb['db']->query($query, $params);
		
		if($result['num_of_rows'] > 0){
			
			if(isset($str)){
				$return = $result['rows'][0]['val'];
			}else{
				foreach($result['rows'] as $row){
					$return[$row['var']] = $row['val'];
				}
			}
			
		}else{
			$return = false;
		}
		
		return $return;
		
	}
	
	/**
	 * unset a key
	 * 
	 * @access	public
	 * @author	Omid Mottaghi
	 * @author	Armin Borumand
	 * @param	string	variable name
	 */
	function remove($var){
	
		global $lb;
		
		$params = array(
				array($this->session_id, 'int'),
				array($var, 'text')
				);
		$query = 'DELETE FROM #__session_store
				WHERE id = # AND var = #';
		$result = $lb['db']->query($query, $params);
		
		if($result['num_of_rows'] == 1){
			return true;
		}else{
			return false;
		}
		
	}
	
	/**
	 * Destroy session
	 *
	 * @access	public
	 * @author	Armin Borumand
	 */
	function destroy(){
		global $lb;
		
		$this->session_id = false;
		//session_destroy();

		$params = array(
				array($this->session_id, 'int')
				);
		$query = 'DELETE FROM #__session WHERE id = #';
		$lb['db']->query($query, $params);
	}

	/**
	 * Clean session database (Remove old session from database)
	 *
	 * @access	public
	 * @author	Armin Borumand
	 * @param	int	for determine old times
	 */
	function clean($time){
		global $lb;
		
		$params = array(
				array($time, 'int')
				);
		$query = 'DELETE A,B 
				FROM lb_session_store AS A
				INNER JOIN lb_session AS B 
					ON B.time < NOW() - #
				WHERE A.id = B.id';
					
		$lb['db']->query($query, $params);
	}
	
	/**
	 * Generate check params
	 *
	 * @access	protected
	 * @author	Armin Borumand
	 * @return	string	check params
	 */
	function check_params(){
		return $_SERVER['HTTP_USER_AGENT'];
	}

	/**
	 * Return number of session
	 *
	 * @access	public
	 * @author	Armin Borumand
	 * @param	int	timestamp
	 * @return	int	number of users
	 */
	function count($timestamp=false){
		global $lb;
		
		$query = 'SELECT count(*) AS count 
				FROM #__session ';
					
		if($timestamp != false){
			$query .= 'WHERE time > TIMESTAMP(NOW() - #)';
			
			$params = array(
					array($timestamp, 'int')
					);
		}else{
			$params = array();
		}
		
		$result = $lb['db']->query($query, $params);
		
		if($result['num_of_rows'] > 0){
			return $result['rows'][0]['count'];
		}else{
			return -1;
		}
	}
	
	/**
	 * Return lb_session errors
	 *
	 * @access	public
	 * @author	Armin Borumand
	 * @return	array		lb_session errors
	 */
	function get_errors(){
		$errors = $this->errs;
		$this->errs = array();
		return $errors;
	}
}

?>
